package dyyx.util;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeType;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.zookeeper.data.Stat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

import dyyx.dto.JmxClient;
import dyyx.dto.ZkClient;

public class WebUtil {
	
	private static final String ERROR = "error";
	private static final String DATA = "data";
	
	private static volatile String  webRootDir = null;
	
	private static Set<String> ignoreMbeanAttrs;
	
			
    static{
    	Set<String> set = new HashSet<String>();
    	set.add("Name");
    	set.add("ObjectName");
    	
    	ignoreMbeanAttrs = Collections.unmodifiableSet(set);
    }
	
	
	public synchronized static void setWebRootDir(String dir){
		if(StringUtils.isBlank(dir)){
			throw new RuntimeException("dir is null");
		}
		if(webRootDir!=null){
			return;
		}
		
	    webRootDir = dir;
	}
	
	
	public static String getWebRootDir(){
		if(webRootDir==null){
			throw new RuntimeException("webRootDir is null");
		}
		
		return  webRootDir;
	}
	
	
	public static void run(HttpServletRequest request, Map<String, Object> map){
		String type = get(request,"type");
		if(StringUtils.isBlank(type)){
			// map.put(ERROR, "type blank");
			// return;
			type = "status";
		}
		try {
			long start = System.currentTimeMillis();
			String methodName = "run_" + type;
			Method method = WebUtil.class.getDeclaredMethod(methodName, HttpServletRequest.class, Map.class);
			method.setAccessible(true);
			method.invoke(null, request, map);
			long end = System.currentTimeMillis();
			long time = end - start;
			map.put("time", time);

			map.put("type", type);
			
			RunStatusUtil.updateCount("run_success_"+type);

			
		} catch (Throwable e) {
			// RunStatusUtil.updateCount("run_error_"+type);

			map.put(ERROR, e + "");
			map.put("errorList", CommUtil.getErrorInfo(e));

		}
		
	}
	
	
	
	private static void run_status(HttpServletRequest request, Map<String, Object> map)throws Exception{
	
		map.put("webRootDir", getWebRootDir());

		map.put(DATA, RunStatusUtil.runStatus);
	}
	
	private static void run_jmxinfo(HttpServletRequest request, Map<String, Object> map)throws Exception{
		String name = get(request,"name");
		if(StringUtils.isBlank(name)){
			map.put(ERROR, "name blank");
			return;
		}
		JmxClient client = ClientUtil.getJmxClient(name);
		map.put(DATA, client);
	}
	
	private static void run_jmxquery(HttpServletRequest request, Map<String, Object> map)throws Exception{
		String name = get(request,"name");
		if(StringUtils.isBlank(name)){
			map.put(ERROR, "name blank");
			return;
		}
		
		String q = get(request,"q");
		if(StringUtils.isBlank(name)){
			q = "*";
		}
		
		
		JmxClient client = ClientUtil.getJmxClient(name);
		// Set<ObjectInstance> mbeans = client.mbeanServerConnection.queryMBeans(new ObjectName(q), null);
		Set<String> names = JmxUtil.queryAsString(client.mbeanServerConnection,q);
		map.put(DATA, names);
	}
	
	
	private static void run_jmxmbean(HttpServletRequest request, Map<String, Object> map) throws Exception {
		String name = get(request, "name");
		if (StringUtils.isBlank(name)) {
			map.put(ERROR, "name blank");
			return;
		}

		String q = get(request, "q");

		if (StringUtils.isBlank(name)) {
			map.put(ERROR, "objectName blank");
			return;
		}

		String obejctName = q;
		JmxClient client = ClientUtil.getJmxClient(name);

		map.put(DATA, JmxUtil.getMBeanAttributeValues(client.mbeanServerConnection, obejctName));
	}
	
	
	private static void run_zkinfo(HttpServletRequest request, Map<String, Object> map)throws Exception{
		String name = get(request,"name");
		if(StringUtils.isBlank(name)){
			map.put(ERROR, "name blank");
			return;
		}
		ZkClient client = ClientUtil.getZkClient(name);
		map.put(DATA, client);
	}
	
	private static void run_zklist(HttpServletRequest request, Map<String, Object> map)throws Exception{
		String name = get(request,"name");
		if(StringUtils.isBlank(name)){
			map.put(ERROR, "name blank");
			return;
		}
		String path = get(request,"path");
		if(StringUtils.isBlank(path)){
			map.put(ERROR, "path blank");
			return;
		}
		
		ZkClient client = ClientUtil.getZkClient(name);
		
		List<String> list = client.zk.getChildren(path, false);
		
		map.put(DATA, list);
	}
	
	private static void run_zkget(HttpServletRequest request, Map<String, Object> map)throws Exception{
		String name = get(request,"name");
		if(StringUtils.isBlank(name)){
			map.put(ERROR, "name blank");
			return;
		}
		String path = get(request,"path");
		if(StringUtils.isBlank(path)){
			map.put(ERROR, "path blank");
			return;
		}
		
		
		ZkClient client = ClientUtil.getZkClient(name);
		Stat stat = new Stat();
		byte[] bytes = client.zk.getData(path, false, stat);
		String  data = CommUtil.toString(bytes);
		map.put(DATA, data);
		map.put("stat", stat);
		
		// map.put(DATA, client);
	}
	
	private static void run_zkreset(HttpServletRequest request, Map<String, Object> map)throws Exception{
		String name = get(request,"name");
		if(StringUtils.isBlank(name)){
			map.put(ERROR, "name blank");
			return;
		}
		ClientUtil.resetZkClient(name);
		
		map.put(DATA, "resetZkClient done "+LocalDateTime.now().toString());
	}
	
	private static void run_reload_config(HttpServletRequest request, Map<String, Object> map)throws Exception{
		
		ConfigUtil.reload();	
		
	}
	
	private static void run_get_config(HttpServletRequest request, Map<String, Object> map)throws Exception{
		map.put(DATA, ConfigUtil.getAllConfig());
	}


	

	
	
	public static String get(HttpServletRequest request, String name) {
		if (request == null || name == null) {
			return null;
		}
		String str = request.getParameter(name);
		if (str != null) {
			str = str.trim();
		}
		return str;
	}

	public static int getInt(HttpServletRequest request, String name) {
		String str = get(request, name);
		return CommUtil.getInt(str);
	}

	public static long getLong(HttpServletRequest request, String name) {
		String str = get(request, name);
		return CommUtil.getLong(str);
	}
	
	public static String toJsonString(Object obj){
		if(obj==null){
			return "";
		}
		return JSON.toJSONString(obj, SerializerFeature.PrettyFormat,SerializerFeature.DisableCircularReferenceDetect);
	}

}
